package com.hanlink.dsp.ca.model.channel;

import androidx.annotation.NonNull;

import com.hanlink.dsp.DspContext;
import com.hanlink.dsp.DspSettings;
import com.hanlink.dsp.protocols.DspProtocol;
import com.qztech.sdk.model.SettingConstants;
import com.qztech.utils.YzDebug;

import org.xutils.db.annotation.Column;
import org.xutils.db.annotation.Table;

import java.io.Serializable;
import java.util.Arrays;

import static com.hanlink.dsp.DspContext.BLE_WRITE_DELAY;
import static com.hanlink.dsp.DspContext.BLE_WRITE_DELAY_LARGE;

@SuppressWarnings("unused")
@Table(name = "_eq_channels")
public class EqChannel implements Serializable {

    @Column(name = "id", isId = true)
    protected int id;

    @Column(name = "channel")
    protected int channel;

    @Column(name = "settings_id")
    private int settingsId;

    private int[] gain = new int[DspSettings.FRENCY_LENGTH]; //所有gain值

    private float[] q = new float[DspSettings.FRENCY_LENGTH]; //所有q值

    private int[] freq = new int[DspSettings.FRENCY_LENGTH]; //所有freq值

    @Column(name = "gain_val")
    private String gainVal = Arrays.toString(gain);

    @Column(name = "q_val")
    private String qVal = Arrays.toString(q);

    @Column(name = "freq_val")
    private String freqVal = Arrays.toString(freq);

    public void resetData(){
        q = DspContext.getDefaultQValues();
        gain = DspContext.getDefaultGainValues();
        freq = DspProtocol.getDefaultChannelValues();
        qVal = Arrays.toString(q);
        freqVal = Arrays.toString(freq);
        gainVal = Arrays.toString(gain);
    }

    public EqChannel() {
        super();
    }
    public void resetQValue(float resetValue) {
        for (int i = 0, len = q.length; i < len; i++) {
            if (q[i] == SettingConstants.Q){
                q[i] =resetValue;
            }
        }
    }
    public EqChannel(int channel, float[] q, int[] gain, int[] freq) {
        this.channel = channel;
        this.gain = gain;
        this.q = q;
        this.freq = freq;
        qVal = Arrays.toString(q);
        freqVal = Arrays.toString(freq);
        gainVal = Arrays.toString(gain);
    }

    public void syncGroupData(EqChannel eqChannel) {
        this.gain = new int[eqChannel.getGain().length];
        for (int i = 0; i < eqChannel.getGain().length; i++) {
            this.gain[i] = eqChannel.getGain()[i];
        }
        this.q = new float[eqChannel.getQ().length];
        for (int i = 0; i < eqChannel.getQ().length; i++) {
            this.q[i] = eqChannel.getQ()[i];
        }
        this.freq = new int[eqChannel.getFreq().length];
        for (int i = 0; i < eqChannel.getFreq().length; i++) {
            this.freq[i] = eqChannel.getFreq()[i];
        }
        qVal = Arrays.toString(q);
        freqVal = Arrays.toString(freq);
        gainVal = Arrays.toString(gain);
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getChannel() {
        return channel;
    }

    public void setChannel(int channel) {
        this.channel = channel;
    }

    public int getSettingsId() {
        return settingsId;
    }

    public void setSettingsId(int settingsId) {
        this.settingsId = settingsId;
    }


    public int[] getGain() {
        return gain;
    }

    public void setGain(int[] gain) {
        this.gain = gain;
    }

    public int getGainValue(int index) {
        if (gain == null || gain.length <= 0 || index > gain.length) return 0;
        return gain[index];
    }

    public void setGainValue(int index, int gain, boolean isGrouping, boolean isReset) {
        if (this.gain == null || this.gain.length <= 0) {
            this.gain = new int[DspSettings.FRENCY_LENGTH];
        }
        this.gain[index] = gain;
        this.gainVal = Arrays.toString(this.gain);
        if (!isReset) {
            if (isGrouping) {
                DspProtocol.writeDoubleEqValue(DspSettings.EQ_SETTINGS.getGroup(channel), index, (int) (q[index]), freq[index], gain);
            } else {
                DspProtocol.writeEqValue(channel, index, (int) (q[index]), freq[index], gain);
            }
        }
    }

    public float getQValue(int index) {
        if (q == null || q.length <= 0 || index > q.length) return 0;
        return q[index];
    }

    public void setQValue(int index, float q, boolean isGrouping, boolean isReset) {
        if (this.q == null || this.q.length <= 0) {
            this.q = new float[DspSettings.FRENCY_LENGTH];
        }
//        YzDebug.d("setQValue index:"+index +" q:"+ q +" isGrouping:"+ isGrouping +" isReset:"+isReset +" " + this);
        this.q[index] = q;
        qVal = Arrays.toString(this.q);
        if (!isReset) {
            if (!isGrouping) {
                DspProtocol.writeEqValue(channel, index, (int) (q), freq[index], gain[index]);
            } else {
                DspProtocol.writeDoubleEqValue(DspSettings.EQ_SETTINGS.getGroup(channel), index, (int) (q), freq[index], gain[index]);
            }
        }
    }

    public void setFreqValue(int index, int freq, boolean isGrouping, boolean isReset) {
        if (this.freq == null || this.freq.length <= 0) {
            this.freq = new int[DspSettings.FRENCY_LENGTH];
        }
        this.freq[index] = freq;
        freqVal = Arrays.toString(this.freq);
        if (!isReset) {
            if (!isGrouping) {
                DspProtocol.writeEqValue(channel, index, (int) (q[index]), freq, gain[index]);
            } else {
                DspProtocol.writeDoubleEqValue(DspSettings.EQ_SETTINGS.getGroup(channel), index, (int) (q[index]), freq, this.gain[index]);
            }
        }
    }


    public float[] getQ() {
        return q;
    }

    public void setQ(float[] q) {
        this.q = q;
    }

    public int[] getFreq() {
        return freq;
    }

    public void setFreq(int[] freq) {
        this.freq = freq;
    }


    public String getGainVal() {
        return gainVal;
    }

    public void setGainVal(String gainVal) {
        this.gainVal = gainVal;
        if (gainVal == null || gainVal.length() <= 0) return;
        String[] tempGain = gainVal.replace("[", "").replace("]", "").split(",");
        try {
            for (int i = 0; i < tempGain.length; i++) {
                this.gain[i] = Integer.parseInt(tempGain[i].trim());
            }
        } catch (Exception ex) {
            System.out.println(" setGainVal ERROR:" + ex);
        }
    }

    public String getQVal() {
        return qVal;
    }


    public void setQVal(String qVal) {
        this.qVal = qVal;
        if (qVal == null || qVal.length() <= 0) return;
        String[] tempGain = qVal.replace("[", "").replace("]", "").split(",");
        try {
            for (int i = 0; i < tempGain.length; i++) {
                this.q[i] = Float.parseFloat(tempGain[i].trim());
            }
        } catch (Exception ex) {
            System.out.println(" setQVal ERROR:" + ex);
        }
    }

    public int getFreqValue(int index) {
        if (freq == null || freq.length <= 0 || index > freq.length) return 0;
        return freq[index];
    }

    public String getFreqVal() {
        return freqVal;
    }

    public void setFreqVal(String freqVal) {
        YzDebug.d("setFreqVal", new Throwable());
        this.freqVal = freqVal;
        if (freqVal == null || freqVal.length() <= 0) return;
        String[] tempGain = freqVal.replace("[", "").replace("]", "").split(",");
        try {
            for (int i = 0; i < freq.length; i++) {
                this.freq[i] = Integer.parseInt(tempGain[i].trim());
            }
        } catch (Exception ex) {
            System.out.println(" setFreqVal ERROR:" + ex);
        }
    }


    private void sendCmd(boolean isGrouping, int index) {
        if (!isGrouping) {
            DspProtocol.writeEqValue(channel, index, (int) (q[index]), freq[index], gain[index]);
        } else {
            DspProtocol.writeDoubleEqValue(DspSettings.EQ_SETTINGS.getGroup(channel), index, (int) (q[index]), freq[index], this.gain[index]);
        }
    }

    public byte[] getCmd(boolean isGrouping, int index) {
        if (!isGrouping) {
            return DspProtocol.getEqBuffer(channel, index, (int) (q[index]), freq[index], gain[index]);
        } else {
            return DspProtocol.getDoubleEqBuffer(DspSettings.EQ_SETTINGS.getGroup(channel), index, (int) (q[index]), freq[index], this.gain[index]);
        }
    }

    public void sendAllCmd(boolean isGrouping) {
        for (int i = 0; i < DspSettings.FRENCY_LENGTH; i++) {
            sendCmd(isGrouping, i);
            try {
                if (i % 5 == 0) {
                    Thread.sleep(BLE_WRITE_DELAY_LARGE);
                } else {
                    Thread.sleep(BLE_WRITE_DELAY);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void sendAllCmdOnNewThread(boolean isGrouping) {
        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < DspSettings.FRENCY_LENGTH; i++) {
                    sendCmd(isGrouping, i);
                    try {
                        Thread.sleep(15);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    private final static String FMT_QVALUE = "%.2f";
    public static String processToQValue(int progress) {
        return String.format(FMT_QVALUE,(progress + SettingConstants.Q_MIN) / 100f);
    }

    public static String qToQValue(float q) {
        return String.valueOf(q / 100d);
    }

    public static int qToProcess(float q) {
        return (int) (q - SettingConstants.Q_MIN);
    }

    public static int processToQ(int process) {
        return process + SettingConstants.Q_MIN;
    }

    public static String gainToValue(int gain) {
        return String.valueOf((gain + SettingConstants.GAIN_MIN) / 10f);
    }

    public static int valueToGain(int value) {
        return value * 10 - SettingConstants.GAIN_MIN;
    }

    @NonNull
    @Override
    public String toString() {
        return "EqChannel{" +
                "id=" + id +
                ", channel=" + channel +
                ", settingsId=" + settingsId +
                ", gainVal='" + gainVal +
                ", qVal='" + qVal +
                ", freqVal='" + freqVal +
                "', gain=" + Arrays.toString(gain) +
                '}';
    }


    public EqChannel copy() {
        final EqChannel ec = new EqChannel();
        ec.id = id;
        ec.channel = channel;
        ec.settingsId = settingsId;
        System.arraycopy(gain,0, ec.gain,0,DspSettings.FRENCY_LENGTH);
        System.arraycopy(q,0, ec.q,0,DspSettings.FRENCY_LENGTH);
        System.arraycopy(freq,0, ec.freq,0,DspSettings.FRENCY_LENGTH);
        ec.gainVal = gainVal;
        ec.qVal = qVal;
        ec.freqVal = freqVal;
        return ec;
    }
}
